package com.gzck.gzck_verson2.webSocket;

import cn.hutool.core.util.ObjectUtil;
import com.gzck.gzck_verson2.pojo.MessageFrame;
import io.swagger.models.auth.In;
import org.springframework.stereotype.Component;

import javax.xml.bind.DatatypeConverter;
import java.util.HashMap;

@Component
public class ModbusMessageParser {

    public MessageFrame parseMessage(String hexMessages) {
        MessageFrame messageFrame = new MessageFrame();

        // 冗余位
        String substring = hexMessages.substring(0, 4);
        if (ObjectUtil.notEqual(substring.toUpperCase(), "7E7E")) {
            throw new RuntimeException("协议不是水纹协议");
//            return null;
        }

        // 去掉冗余位后的报文
        String hexMessage = hexMessages.substring(4);

        // 中心站地址
        messageFrame.setCenterStationAddress(hexMessage.substring(0, 2));

        // 遥测站ID
        messageFrame.setRemoteStationId(hexMessage.substring(2, 12));

        // 通讯密码
        messageFrame.setCommunicationPassword(hexMessage.substring(12, 16));

        // 功能码
        messageFrame.setFunctionCode(hexMessage.substring(16, 18));
//
//        // 报文上下行标识及长度
//        messageFrame.setUpOrDown(hexMessage.substring(18, 20));

        // 报文长度
        messageFrame.setMessageBodyLength(Integer.parseInt(hexMessage.substring(18, 22), 16));

        // 正文起始符
        messageFrame.setMessageStart(hexMessage.substring(22, 24));


        // 流水号
        messageFrame.setSerialNumber(hexMessage.substring(24, 28));

        // 发报时间
        messageFrame.setTransmissionTime(hexMessage.substring(28, 40));

        // 遥测站标识
        messageFrame.setRemoteStationIdentifier(hexMessage.substring(40, 44));

        // 遥测站ID
        messageFrame.setRemoteStationCode(hexMessage.substring(44, 54));

        // 遥测站分类码
        messageFrame.setRemoteStationCategory(hexMessage.substring(54, 56));

        // 观测时间标识
        messageFrame.setObservationTimeIdentifier(hexMessage.substring(56, 60));

        // 观测时间
        messageFrame.setObservationTime(hexMessage.substring(60, 70));


        //不定长正文 存messageBody
        HashMap<String, Object> messageBody = new HashMap<>();

        String frameMessageBody = hexMessage.substring(70);

        parseMessageBody(messageFrame, frameMessageBody, messageBody);

        messageFrame.setMessageBody(messageBody);

        return messageFrame;
    }

    /**
     * 解析报文正文
     * @param messageFrame   存储单位
     * @param hexMessages  报文字符串
     * @param messageBody   存储集合
     */
    public void parseMessageBody(MessageFrame messageFrame, String hexMessages, HashMap<String, Object> messageBody) {
        int count = 0;
        //获得实际的长度
        Integer length = messageFrame.getMessageBodyLength() - 23;
        while (true) {
            String start = hexMessages.substring(count, count + 2);

            //如果是非FF
            if (ObjectUtil.notEqual(start, "FF")) {
                count += 2;
                String binaryString = Integer.toBinaryString(Integer.parseInt(hexMessages.substring(count, count + 2), 16));
                count += 2;

                HashMap<String, Integer> stringIntegerHashMap = parseBinaryString(binaryString);
                Integer dacimalPlaces = stringIntegerHashMap.get("decimalPlaces");
                Integer dataLength = stringIntegerHashMap.get("dataLength");
                String body = hexMessages.substring(count, count + dataLength * 2);

                count += dataLength * 2;
                //数据转换
                float result = convertToFloat(body, dacimalPlaces);
                messageBody.put(start, result);
                //判断是否结束
//                ObjectUtil.equal(hexMessages.substring(count, count + 2), "03") &
                if ( count + 2 > length * 2) {
                    break;
                }
            }
            //如果是FF
            if (ObjectUtil.equal(start, "FF")){
                start = hexMessages.substring(count, count + 4);
                count += 4;
                String binaryString = Integer.toBinaryString(Integer.parseInt(hexMessages.substring(count, count + 2), 16));
                count += 2;
                HashMap<String, Integer> stringIntegerHashMap = parseBinaryString(binaryString);
                Integer dacimalPlaces = stringIntegerHashMap.get("decimalPlaces");
                Integer dataLength = stringIntegerHashMap.get("dataLength");
                String body = hexMessages.substring(count, count + dataLength * 2);
                count += dataLength * 2;
                //数据转换
                float result = convertToFloat(body, dacimalPlaces);
                messageBody.put(start, result);
                //判断是否结束
//                ObjectUtil.equal(hexMessages.substring(count, count + 2), "03") &
                if ( count + 2 > length * 2) {
                    break;
                }
            }

        }
    }

    /**
     * 解析非FF的字符串内容和长度
     *
     * @param binaryString
     */
    private HashMap<String, Integer> parseBinaryString(String binaryString) {
        while (binaryString.length() < 8) {
            binaryString = "0" + binaryString;
        }

        // 前5位表示数据长度
        int dataLength = Integer.parseInt(binaryString.substring(0, 5), 2);

        // 后3位表示小数位
        int decimalPlaces = Integer.parseInt(binaryString.substring(5), 2);
        HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
        stringIntegerHashMap.put("dataLength", dataLength);
        stringIntegerHashMap.put("decimalPlaces", decimalPlaces);
        return stringIntegerHashMap;
    }


    /**
     * 将十进制字符串转换为浮点数
     *
     * @param decimalString
     * @param decimalPlaces
     */
    float convertToFloat(String decimalString, int decimalPlaces) {
        System.out.println(decimalString);

        // 获取前八位
        String leadingBits = decimalString.substring(0, Math.min(8, decimalString.length()));

        // 判断前八位是否都是1
        boolean isNegative =  leadingBits.startsWith("FF");

        //移除左侧的八位1
        if (isNegative){
            decimalString  =   decimalString.substring(2);
        }


        // 移除左侧的零
        String trimmedDecimal = decimalString.replaceFirst("^0+", "");

        // 如果传入的字符串全为零，直接返回0
        if (trimmedDecimal.isEmpty()) {
            return 0.0f;
        }

        // 计算浮点数
        float floatValue = Float.parseFloat(trimmedDecimal);

        // 添加小数位
        for (int i = 0; i < decimalPlaces; i++) {
            floatValue /= 10.0;
        }

        // 如果是负数，添加负号
        if (isNegative) {
            floatValue *= -1;
        }

        // 转换为字符串，以便截取小数点后指定位数
        String resultString = Float.toString(floatValue);

        // 截取小数点后指定位数
        int dotIndex = resultString.indexOf('.');
        if (dotIndex != -1 && resultString.length() > dotIndex + decimalPlaces + 1) {
            resultString = resultString.substring(0, dotIndex + decimalPlaces + 1);
        }

        // 转换回浮点数
        floatValue = Float.parseFloat(resultString);

        return floatValue;
    }


}
